home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / manchester / 2.2 / TerminalEmulators.st < prev    next >
Text File  |  1993-07-24  |  36KB  |  1,343 lines

  1. "    NAME        TerminalEmulators
  2.     AUTHOR        tph@cs.man.ac.uk
  3.     FUNCTION VS100/VT100 etc emulators 
  4.     ST-VERSIONS    2.2
  5.     PREREQUISITES     
  6.     CONFLICTS    
  7.     DISTRIBUTION      world
  8.     VERSION        1.1
  9.     DATE    22 Jan 1989
  10. SUMMARY    TerminalEmulators
  11.     provides a number of `intelligent' terminal
  12.    emulators, including VS100 (large and small) and Newbury terminals.
  13.    The small VS100 emulator seems to provide a reasonable imitation of
  14.    a VT100 as well.
  15.  
  16.    This    goodie is known to work only with VI2.2 images.  Some work will
  17.    be required to get it to function with earlier images. TPH
  18. "!
  19. 'From Smalltalk-80, Version 2.2 of July 4, 1987 on 6 September 1987 at 2:20:00 pm'!
  20.  
  21.  
  22.  
  23. !Character class methodsFor: 'accessing untypeable characters'!
  24.  
  25. bell
  26.     "Answer the Character representing a bell."
  27.  
  28.     ^self value: 7! !'From Smalltalk-80, Version 2.2 of July 4, 1987 on 5 September 1987 at 5:32:58 pm'!
  29.  
  30.  
  31.  
  32. !Character class methodsFor: 'accessing untypeable characters'!
  33.  
  34. null
  35.     "Answer the Character representing a null."
  36.  
  37.     ^self value: 0! !'From Smalltalk-80, Version 2.2 of July 4, 1987 on 5 September 1987 at 5:33:03 pm'!
  38.  
  39.  
  40.  
  41. !CharacterScanner methodsFor: 'access'!
  42.  
  43. font: aFont
  44.     "Make the font used aFont."
  45.  
  46.     font _ aFont! !'From Smalltalk-80, Version 2.2 of July 4, 1987 on 5 September 1987 at 5:33:06 pm'!
  47.  
  48.  
  49.  
  50. !CharacterScanner methodsFor: 'access'!
  51.  
  52. outputMedium: aDisplayMedium
  53.     "Set the display medium to be used to aDisplayMedium."
  54.  
  55.     outputMedium _ aDisplayMedium! !'From Smalltalk-80, Version 2.2 of July 4, 1987 on 5 September 1987 at 5:33:14 pm'!
  56.  
  57.  
  58.  
  59. !CharacterScanner methodsFor: 'access'!
  60.  
  61. spaceWidth: aWidth
  62.  
  63.     spaceWidth _ aWidth! !'From Smalltalk-80, Version 2.2 of July 4, 1987 on 5 September 1987 at 5:33:18 pm'!
  64.  
  65.  
  66.  
  67. !CharacterScanner methodsFor: 'access'!
  68.  
  69. stopConditions
  70.     "Answer with the stop conditions."
  71.  
  72.     ^stopConditions! !'From Smalltalk-80, Version 2.2 of July 4, 1987 on 5 September 1987 at 5:33:21 pm'!
  73.  
  74.  
  75.  
  76. !CharacterScanner methodsFor: 'access'!
  77.  
  78. text: aText
  79.     "Make the text used aText."
  80.  
  81.     text _ aText! !'From Smalltalk-80, Version 2.2 of July 4, 1987 on 5 September 1987 at 5:33:25 pm'!
  82.  
  83.  
  84.  
  85. !CharacterScanner methodsFor: 'access'!
  86.  
  87. textStyle: aTextStyle
  88.     "Make the textStyle used aTextStyle."
  89.  
  90.     textStyle _ aTextStyle! !'From Smalltalk-80, Version 2.2 of July 4, 1987 on 5 September 1987 at 5:34:11 pm'!
  91.  
  92.  
  93.  
  94. !ExternalPort methodsFor: 'intialize-release'!
  95.  
  96. initializePort
  97.  
  98.     receiveBuffer _ ByteArray new: 10240.
  99.     receiveSemaphore _ Semaphore new.
  100.     sendSemaphore _ Semaphore new.
  101.     Smalltalk addDependent: self! !Model subclass: #TermEmulator
  102.     instanceVariableNames: 'contents x y displayProcess serialPort numberOfColumns numberOfLines changedLines '
  103.     classVariableNames: ''
  104.     poolDictionaries: ''
  105.     category: 'Interface-TerminalEmulator'!
  106. TermEmulator comment:
  107. 'I represent a model for a basic terminal emulator.  Instances of me can be
  108. used, together with an instance of TermEmulatorController and an instance
  109. of TermEmulatorView, to provide a simple (dumb) terminal interface to the
  110. underlying Unix system.
  111.  
  112. Instance variables:
  113.  
  114. contents        An OrderedCollection of ByteArrays, used to contain the
  115.                 actual characters represented by me.
  116.  
  117. x                The current x location of the cursor.
  118.  
  119. y                The current y location of the cursor.
  120.  
  121. displayProcess    The process which runs asynchonously, which gets characters
  122.                 from the input port.
  123.  
  124. serialPort        The serial port currently being used.
  125.  
  126. numberOfColumns, numberOfLines -- the size of the (emulated) screen.
  127.  
  128. changedLines    An Array of Boolean values, indicating which lines have been
  129.                 changed.  This is used to improve the performance, by ensuring
  130.                 that the same line is not updated unnecessarily.
  131. '!
  132.  
  133.  
  134. !TermEmulator methodsFor: 'initialize-release'!
  135.  
  136. initialize
  137.     "Initialize the contents of the receiver.  If this message is
  138.      overridden by a subclass, make use that the expression
  139.      'super initialize' is included."
  140.  
  141.     self initializeLinesAndColumns.
  142.     self clear.
  143.     self home!
  144.  
  145. release
  146.  
  147.     self close.
  148.     super release! !
  149.  
  150. !TermEmulator methodsFor: 'accessing'!
  151.  
  152. contentsAt: aLine
  153.     "Answer with the String which form the contents of the receiver
  154.      at aLine."
  155.  
  156.     ^contents at: aLine!
  157.  
  158. cursorLocation
  159.     "Answer with a point representing the current location of the cursor."
  160.  
  161.     ^x @ y!
  162.  
  163. numberOfColumns
  164.     "Answer with the number of columns of characters are represented
  165.      by the receiver."
  166.  
  167.     ^numberOfColumns!
  168.  
  169. numberOfLines
  170.     "Answer with the number of lines of characters are represented
  171.      by the receiver."
  172.  
  173.     ^numberOfLines!
  174.  
  175. serialPort
  176.     "Answer with the serial port to which the receiver is attached."
  177.  
  178.     ^serialPort! !
  179.  
  180. !TermEmulator methodsFor: 'port control'!
  181.  
  182. close
  183.     "If the serial port is open, close it."
  184.  
  185.     (serialPort notNil and: [serialPort isOpen])
  186.         ifTrue: [serialPort removeDependent: self.
  187.                 serialPort release.
  188.                 serialPort close]!
  189.  
  190. reset
  191.     "Reset the serial port.  Sometimes useful if a disaster occurs."
  192.  
  193.     (serialPort notNil and: [serialPort isOpen])
  194.         ifTrue: [serialPort reset]! !
  195.  
  196. !TermEmulator methodsFor: 'character handling'!
  197.  
  198. displayCharacter: char
  199.     "Interpret char appropriately."
  200.  
  201.     char isAlphaNumeric ifTrue: [
  202.         self processPrintingCharacter: char.
  203.         ^self advanceCursor].
  204.     char = Character null ifTrue: [^self].
  205.     char = Character cr ifTrue: [^self processCRCharacter].
  206.     char = Character lf ifTrue: [^self processLFCharacter].
  207.     char = Character backspace ifTrue: [^self processBackspaceCharacter].
  208.     char = Character bell ifTrue: [^self processBellCharacter].
  209.     char = Character tab ifTrue: [^self processTabCharacter].
  210.     self processPrintingCharacter: char.
  211.     self advanceCursor!
  212.  
  213. displayCharacters
  214.     "This is where incoming characters are interpreted."
  215.  
  216.     self changed: #cursor.
  217.     [serialPort atEnd] whileFalse: [
  218.         self displayCharacter: serialPort next asCharacter].
  219.     self changed: y.
  220.     1 to: numberOfLines do: [:eachLine |
  221.         (changedLines at: eachLine) ifTrue: [super changed: eachLine]].
  222.     changedLines atAllPut: false.
  223.     self changed: #cursor!
  224.  
  225. processBackspaceCharacter
  226.     "Deal with a backspace character."
  227.  
  228.     x > 1 ifTrue: [x _ x - 1]!
  229.  
  230. processBellCharacter
  231.     "Deal with a bell character."
  232.  
  233.     self changed: #flash!
  234.  
  235. processCRCharacter
  236.     "Deal with a Carriage Return (CR) character."
  237.  
  238.     x _ 1!
  239.  
  240. processLFCharacter
  241.     "Deal with a Line Feed (LF) character."
  242.  
  243.     self changed: y.
  244.     (y >= numberOfLines)
  245.         ifTrue: [self scroll]
  246.         ifFalse: [y _ y + 1].
  247.     Processor yield!
  248.  
  249. processPrintingCharacter: char
  250.     "The character char is assumed to be a printing character.  Add
  251.      it to the model appropriately."
  252.  
  253.     (contents at: y) at: x put: char asciiValue!
  254.  
  255. processTabCharacter
  256.     "Add one or more space characters to get the cursor to the next tab stop."
  257.  
  258.     self processPrintingCharacter: Character space.
  259.     self advanceCursor.
  260.     x < (numberOfColumns - 8) ifTrue: [
  261.         [x isMultipleOf: 8] whileFalse: [
  262.         self processPrintingCharacter: Character space.
  263.         self advanceCursor]]! !
  264.  
  265. !TermEmulator methodsFor: 'display manipulation'!
  266.  
  267. advanceCursor
  268.     "Move the cursor one to the right, provided that we are
  269.      not already at the right-hand edge."
  270.  
  271.     (x < numberOfColumns) ifTrue: [x _ x + 1]!
  272.  
  273. clear
  274.     "Clear the contents of the receiver."
  275.  
  276.     contents _ OrderedCollection new: numberOfLines.
  277.     numberOfLines timesRepeat: [contents addLast:
  278.         (ByteArray new: numberOfColumns withAll: 32)].
  279.     changedLines _ Array new: numberOfLines withAll: false.!
  280.  
  281. home
  282.     "Return the cursor to the top left of the (simulated) screen."
  283.  
  284.     x _ 1.
  285.     y _ 1!
  286.  
  287. scroll
  288.     "Scroll up the receiver by one line."
  289.  
  290.     self changed: #scroll.
  291.     self scrollBy: 1.!
  292.  
  293. scrollBy: aNumber
  294.     "Scroll up the receiver aNumber lines."
  295.  
  296.     (aNumber < numberOfLines) ifFalse: [^self clear].
  297.     aNumber timesRepeat: [
  298.         contents removeFirst.
  299.         contents addLast: (ByteArray new: numberOfColumns withAll: 32)].! !
  300.  
  301. !TermEmulator methodsFor: 'updating'!
  302.  
  303. changed: parameter
  304.     "Intercept this to ensure that multiple updates to the same
  305.      line are not carried out."
  306.  
  307.     (parameter isKindOf: Number) ifTrue: [
  308.         ^changedLines at: parameter put: true].
  309.     (parameter == #scroll) ifTrue: [
  310.         1 to: numberOfLines do: [:eachLine |
  311.             (changedLines at: eachLine) ifTrue: [super changed: eachLine]].
  312.         changedLines atAllPut: false].
  313.     super changed: parameter!
  314.  
  315. update: parameter
  316.     "Process a dependency message"
  317.  
  318.     parameter == #closeBeforeSnapshot
  319.         ifTrue: [^displayProcess terminate].
  320.     parameter == #openAfterSnapshot
  321.         ifTrue: [^self startReceiveProcess].
  322.     parameter == #externalPortError
  323.         ifTrue: [self close.
  324.                 ^self changed: #externalPortError]! !
  325.  
  326. !TermEmulator methodsFor: 'private'!
  327.  
  328. initializeLinesAndColumns
  329.     "Set the default number of lines and columns."
  330.  
  331.     self setLines: 24.
  332.     self setColumns: 80!
  333.  
  334. sendAll: aString
  335.     "Send out some of the user's input."
  336.  
  337.     (serialPort notNil and: [aString size > 0])
  338.         ifFalse: [^false]
  339.         ifTrue: [^(serialPort sendBuffer: aString) ~~ nil]!
  340.  
  341. setColumns: aNumber
  342.  
  343.     numberOfColumns _ aNumber!
  344.  
  345. setLines: aNumber
  346.  
  347.     numberOfLines _ aNumber!
  348.  
  349. setSerialPort: aSerialPort
  350.  
  351.     serialPort isNil ifFalse: [serialPort removeDependent: self].
  352.     serialPort _ aSerialPort    .
  353.     serialPort addDependent: self.!
  354.  
  355. startReceiveProcess
  356.     "Fires up the background process that will run in parallel with the 
  357.      user's input."
  358.  
  359.     displayProcess _ 
  360.             [[serialPort notNil and: [serialPort isOpen]] whileTrue: [
  361.                     serialPort receiveBuffer.
  362.                     self displayCharacters]] newProcess.
  363.     displayProcess priority: Processor userSchedulingPriority.
  364.     displayProcess resume.! !
  365. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  366.  
  367. TermEmulator class
  368.     instanceVariableNames: ''!
  369.  
  370.  
  371. !TermEmulator class methodsFor: 'instance creation'!
  372.  
  373. new
  374.     "Answer with a new instance of the receiver."
  375.  
  376.     ^super new initialize!
  377.  
  378. openShell
  379.     "TermEmulator openShell."
  380.  
  381.     TermEmulatorView
  382.         openOn: (self getTerminal)
  383.         label: 'Dumb TTY'!
  384.  
  385. openShell: aNumber
  386.     "TermEmulator openShell: 1."
  387.  
  388.     TermEmulatorView
  389.         openOn: (self getTerminal: aNumber)
  390.         label: 'Dumb TTY'! !
  391.  
  392. !TermEmulator class methodsFor: 'private'!
  393.  
  394. getPort
  395.     "Get a shell port with any available number."
  396.  
  397.     | port aShellNumber |
  398.     port _ nil.
  399.     aShellNumber _ 1.
  400.     [port isNil] whileTrue: [
  401.         port _ CShellPort open: aShellNumber.
  402.         aShellNumber _ aShellNumber + 1.
  403.         aShellNumber > 8 ifTrue: [
  404.             ^self error: 'unable to open shell ', aShellNumber printString]].
  405.     ^port!
  406.  
  407. getPort: aNumber
  408.     "Get a shell port corresponding to aNumber."
  409.  
  410.     | port |
  411.     port _ CShellPort open: aNumber.
  412.     port isNil ifTrue: [^self error: 'unable to open shell ', aNumber printString].
  413.     ^port!
  414.  
  415. getTerminal
  416.     "Get an instance of the receiver, with a shell port with
  417.      any available number attached to it."
  418.  
  419.     ^self new setSerialPort: (self getPort)!
  420.  
  421. getTerminal: aNumber
  422.     "Answer with an instance of the receiver connected to a
  423.      port given by aNumber."
  424.  
  425.     ^self new setSerialPort: (self getPort: aNumber)! !
  426.  
  427. View subclass: #TermEmulatorView
  428.     instanceVariableNames: 'style scanner '
  429.     classVariableNames: 'CharHeight '
  430.     poolDictionaries: ''
  431.     category: 'Interface-TerminalEmulator'!
  432. TermEmulatorView comment:
  433. 'I represent the view of a simple terminal emulator.
  434.  
  435. style        A TextStyle, which should be a fixed width text style.
  436.  
  437. scanner        A CharacterScanner, used to display the characters.  This
  438.             is a grubby hack, but used to try and improve the performance.
  439.  
  440. '!
  441.  
  442.  
  443. !TermEmulatorView methodsFor: 'initialize-release'!
  444.  
  445. initialize
  446.     "Initialize the style used to display the contents."
  447.  
  448.     self initializeScanner.
  449.     super initialize! !
  450.  
  451. !TermEmulatorView methodsFor: 'displaying'!
  452.  
  453. displayContents
  454.     "Display the contents of the model using the current text style."
  455.  
  456.     self displaySafe: [
  457.         1 to: self model numberOfLines do: [:eachLine |
  458.             self reallyDisplayLine: eachLine]]!
  459.  
  460. displayCursor
  461.     "Display (or remove) the cursor."
  462.  
  463.     self displaySafe: [
  464.         Display reverse: (self model cursorLocation * (7@CharHeight)
  465.             + (-3@-12) + self insetDisplayBox topLeft
  466.                 extent: 7@CharHeight)]!
  467.  
  468. displayLine: aNumber
  469.     "Display the line of the model indicated by aNumber."
  470.  
  471.     self displaySafe: [self reallyDisplayLine: aNumber]!
  472.  
  473. displayScroll
  474.     "Copy the form up as in the scrolling operation."
  475.  
  476.     Display
  477.         copy: (insetDisplayBox topLeft + (0@2)
  478.                     extent: (insetDisplayBox width)@(model numberOfLines -1 * CharHeight))
  479.         from: (insetDisplayBox topLeft + (0@(2+CharHeight)))
  480.         in: Display
  481.         rule: Form over!
  482.  
  483. displayView
  484.     "Display the contents of the model and the cursor."
  485.  
  486.     self displayContents.
  487.     self displayCursor!
  488.  
  489. reallyDisplayLine: aNumber 
  490.     "Display the line of the model indicated by aNumber."
  491.  
  492.     scanner clipRect: insetDisplayBox.
  493.     scanner destOrigin:    (4 @ (aNumber - 1 * CharHeight + 2)) + insetDisplayBox topLeft.
  494.     scanner
  495.         scanCharactersFrom: 1
  496.         to: model numberOfColumns
  497.         in: (model contentsAt: aNumber)
  498.         rightX: insetDisplayBox right
  499.         stopConditions: scanner stopConditions
  500.         displaying: true! !
  501.  
  502. !TermEmulatorView methodsFor: 'updating'!
  503.  
  504. update: aParameter
  505.     "The model has changed, so update the display in some way."
  506.  
  507.     aParameter == #flash ifTrue: [^self flash].
  508.     self topView isCollapsed ifFalse: [
  509.         aParameter == #cursor ifTrue: [^self displayCursor].
  510.         aParameter == #clear ifTrue: [^self displaySafe: [self clearInside]].
  511.         aParameter == #scroll ifTrue: [
  512.             ^self displaySafe: [self displayScroll]].
  513.         (aParameter isKindOf: Number) ifTrue: [^self displayLine: aParameter]]! !
  514.  
  515. !TermEmulatorView methodsFor: 'controller access'!
  516.  
  517. defaultControllerClass
  518.  
  519.     ^TermEmulatorController! !
  520.  
  521. !TermEmulatorView methodsFor: 'private'!
  522.  
  523. flash
  524.     "Flash either the view once (if open) or the label three
  525.      times (if collapsed)."
  526.  
  527.     self topView isCollapsed
  528.         ifTrue: [
  529.             3 timesRepeat: [self topView iconView flash]]
  530.         ifFalse: [
  531.             super flash]!
  532.  
  533. initializeScanner
  534.     "Initialize the character scanner used for displaying."
  535.  
  536.     | font |
  537.     style _ TextStyle styleNamed: #fixed ifAbsent: [
  538.         ^self error: 'fixed width text style not available'].
  539.     font _ style defaultFont.
  540.     scanner _ CharacterScanner new.
  541.     scanner combinationRule: Form over.
  542.     scanner destForm: Display.
  543.     scanner mask: nil.
  544.     scanner sourceY: 0.
  545.     scanner font: font.
  546.     scanner spaceWidth: (font widthOf: Character space).
  547.     scanner sourceForm: font glyphs.
  548.     scanner xTable: font xTable.
  549.     scanner height: font height.
  550.     scanner textStyle: style.
  551.     scanner outputMedium: Display.
  552.     scanner stopConditions: (Array new: 258).! !
  553. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  554.  
  555. TermEmulatorView class
  556.     instanceVariableNames: ''!
  557.  
  558.  
  559. !TermEmulatorView class methodsFor: 'instance creation'!
  560.  
  561. openOn: aTermEmulator label: aString
  562.     "Create a new instance of the receiver with the model
  563.      being aTermEmulator and the label aString."
  564.  
  565.     | size topView aView |
  566.     size _ (aTermEmulator numberOfColumns * 7 + 12) @
  567.                 (aTermEmulator numberOfLines * CharHeight + 7).
  568.     topView _ StandardSystemView
  569.                 model: aTermEmulator
  570.                 label: aString
  571.                 minimumSize: size.
  572.     topView maximumSize: size.
  573.     topView icon: (Icon constantNamed: #terminal).
  574.     topView borderWidth: 1.
  575.     topView borderColor: Form black.
  576.     aView _ self new model: aTermEmulator.
  577.     aView insideColor: Form white.
  578.     topView addSubView: aView in: (0@0 extent: 1@1) borderWidth: 1.
  579.     topView controller openNoTerminate.
  580.     aTermEmulator startReceiveProcess.
  581.     Cursor normal show.
  582.     Processor terminateActive! !
  583.  
  584. !TermEmulatorView class methodsFor: 'class initialization'!
  585.  
  586. initialize
  587.     "Initialize class variables."
  588.     "TermEmulatorView initialize."
  589.  
  590.     CharHeight _ 13! !
  591.  
  592. TermEmulatorView initialize!
  593.  
  594.  
  595. TermEmulator subclass: #IntelligentEmulator
  596.     instanceVariableNames: 'autoMargin autoLineFeed displayMode emphasis '
  597.     classVariableNames: ''
  598.     poolDictionaries: ''
  599.     category: 'Interface-TerminalEmulator'!
  600. IntelligentEmulator comment:
  601. 'I add the functionality to support emulation of various types
  602. of ''intelligent'' terminals (i.e. ones which support cursor movement, etc.).
  603. I am an abstract superclass; subclasses of me should add the functionality
  604. to interpret the incoming character stream.
  605.  
  606. Instance variables:
  607.  
  608. autoMargin        A Boolean, indicating whether an automatic ''line-feed'' operation
  609.                 is performed when the cursor hits the right-hand margin.  Normally
  610.                 true.
  611.  
  612. autoLineFeed    A Boolean, indicating whether an automatic ''line-feed'' operation
  613.                 is performed when a ''carriage return'' character is received.
  614.                 Normally false.
  615.  
  616. displayMode    An Integer, indicating which type of emphasis should be used for
  617.                 incoming characters.
  618.  
  619. emphasis        An OrderedCollection of ByteArrays, containing the emphasising
  620.                 information for the corresponding characters.
  621. '!
  622.  
  623.  
  624. !IntelligentEmulator methodsFor: 'initialize-release'!
  625.  
  626. initialize
  627.     "Initialize various flags."
  628.  
  629.     super initialize.
  630.     self resetDefaults! !
  631.  
  632. !IntelligentEmulator methodsFor: 'accessing'!
  633.  
  634. autoMargin: aBoolean
  635.     "Set the value of the automatic margin flag."
  636.  
  637.     autoMargin _ aBoolean!
  638.  
  639. displayMode: anInteger
  640.     "Set the current display mode."
  641.  
  642.     displayMode _ anInteger!
  643.  
  644. emphasisAt: aLine
  645.     "Answer with the Array which represents the emphasis on the line."
  646.  
  647.     ^emphasis at: aLine! !
  648.  
  649. !IntelligentEmulator methodsFor: 'character handling'!
  650.  
  651. processCRCharacter
  652.     "If the autoLineFeed flag is set, do an automatic LF after the CR."
  653.  
  654.     super processCRCharacter.
  655.     autoLineFeed ifTrue: [self processLFCharacter]!
  656.  
  657. processPrintingCharacter: char
  658.     "Add the functionality required to handle emphasis."
  659.  
  660.     super processPrintingCharacter: char.
  661.     (emphasis at: y) at: x put: displayMode! !
  662.  
  663. !IntelligentEmulator methodsFor: 'display manipulation'!
  664.  
  665. addLine
  666.     "Add a blank line at the position indicated by the cursor."
  667.  
  668.     self addLines: 1!
  669.  
  670. addLines: aNumber
  671.     "Add aNumber blank lines at the position indicated by the cursor."
  672.  
  673.     aNumber timesRepeat: [
  674.         contents add: (ByteArray new: numberOfColumns withAll: 32) beforeIndex: y.
  675.         emphasis add: (ByteArray new: numberOfColumns withAll: 0) beforeIndex: y.        
  676.         contents removeLast.
  677.         emphasis removeLast].
  678.     y to: numberOfLines do: [:eachLine | self changed: eachLine]!
  679.  
  680. advanceCursor
  681.     "If the cursor is already at the right-hand edge, do an automatic
  682.      margin operation if the appropriate flag is set."
  683.  
  684.     (x < numberOfColumns) ifTrue: [x _ x + 1.  ^self].
  685.     autoMargin ifTrue: [
  686.         self processCRCharacter.
  687.         self processLFCharacter]!
  688.  
  689. clear
  690.     "Clear the display."
  691.  
  692.     super clear.
  693.     emphasis _ OrderedCollection new.
  694.     numberOfLines timesRepeat: [
  695.         emphasis addLast: (ByteArray new: numberOfColumns withAll: 0)]!
  696.  
  697. clearEntireLine
  698.     "Clear the entire line."
  699.  
  700.     (contents at: y) atAllPut: 32.
  701.     (emphasis at: y) atAllPut: 0.
  702.     self changed: y!
  703.  
  704. clearFromBeginningOfDisplay
  705.     "Clear the simulated screen from the start to the current location."
  706.  
  707.     1 to: y - 1 do: [:eachLine |
  708.         contents at: eachLine put: (ByteArray new: numberOfColumns withAll: 32).
  709.         emphasis at: eachLine put: (ByteArray new: numberOfColumns withAll: 0).
  710.         self changed: eachLine].
  711.     self clearFromBeginningOfLine.!
  712.  
  713. clearFromBeginningOfLine
  714.     "Clear from the beginning of the line to the cursor."
  715.  
  716.     1 to: x do: [:eachColumn |
  717.         (contents at: y) at: eachColumn put: 32.
  718.         (emphasis at: y) at: eachColumn put: 0].
  719.     self changed: y!
  720.  
  721. clearToEndOfDisplay
  722.     "Clear the simulated screen from the current location to the end."
  723.  
  724.     self clearToEndOfLine.
  725.     y + 1 to: numberOfLines do: [:eachLine |
  726.         contents at: eachLine put: (ByteArray new: numberOfColumns withAll: 32).
  727.         emphasis at: eachLine put: (ByteArray new: numberOfColumns withAll: 0).
  728.         self changed: eachLine]!
  729.  
  730. clearToEndOfLine
  731.     "Clear from the current cursor position to the end of the line."
  732.  
  733.     x to: numberOfColumns do: [:eachColumn |
  734.         (contents at: y) at: eachColumn put: 32.
  735.         (emphasis at: y) at: eachColumn put: 0].
  736.     self changed: y!
  737.  
  738. cursorDown: aNumber
  739.     "Move the cursor down the appropriate number of lines."
  740.  
  741.     self moveToX: x y: y + aNumber!
  742.  
  743. cursorLeft: aNumber
  744.     "Move the cursor left (in a non-destructive manner) the
  745.      appropriate number of places."
  746.  
  747.     self moveToX: x - aNumber y: y!
  748.  
  749. cursorRight: aNumber
  750.     "Move the cursor right (in a non-destructive manner) the 
  751.      appropriate number of places."
  752.  
  753.     self moveToX: x + aNumber y: y!
  754.  
  755. cursorUp: aNumber
  756.     "Move the cursor up the appropriate number of lines, unless the cursor 
  757.      would overflow at the top."
  758.  
  759.     self moveToX: x y: y - aNumber!
  760.  
  761. deleteCharacter
  762.     "Delete a character position at the current cursor location."
  763.  
  764.     | line |
  765.     line _ (contents at: y).
  766.     x to: numberOfColumns - 1 do: [:eachPos |
  767.         line at: eachPos put: (line at: eachPos + 1)].
  768.     line at: numberOfColumns put: 32.
  769.     self changed: y!
  770.  
  771. deleteLine
  772.     "Delete the line at the position indicated by the cursor."
  773.  
  774.     self deleteLines: 1!
  775.  
  776. deleteLines: aNumber
  777.     "Delete the line at the position indicated by the cursor."
  778.  
  779.     aNumber timesRepeat: [
  780.         contents removeAtIndex: y.
  781.         emphasis removeAtIndex: y.
  782.         contents addLast: (ByteArray new: numberOfColumns withAll: 32).
  783.         emphasis addLast: (ByteArray new: numberOfColumns withAll: 0)].
  784.     y to: numberOfLines do: [:eachLine |
  785.         self changed: eachLine].!
  786.  
  787. doNothing
  788.     "Used when a sequence is defined, but not implemented here."
  789.  
  790.     ^self!
  791.  
  792. insertCharacter
  793.     "Insert a character position at the current cursor location."
  794.  
  795.     | line |
  796.     line _ (contents at: y).
  797.     numberOfColumns to: x + 1 by: -1 do: [:eachPos |
  798.         line at: eachPos put: (line at: eachPos - 1)].
  799.     line at: x put: 32.
  800.     self changed: y!
  801.  
  802. moveToX: xLocation y: yLocation
  803.     "Position the cursor at the location given by xLocation and yLocation.
  804.      Ignore the command if the parameters are outside the allowable range."
  805.  
  806.     (xLocation < 1 or: [xLocation > numberOfColumns]) ifTrue: [^self].
  807.     (yLocation < 1 or: [yLocation > numberOfLines]) ifTrue: [^self].
  808.     self changed: y.
  809.     x _ xLocation.
  810.     y _ yLocation!
  811.  
  812. scrollBy: aNumber
  813.     "Scroll up the receiver aNumber lines.  Override to add functionality
  814.      for emphasis."
  815.  
  816.     super scrollBy: aNumber.
  817.     aNumber timesRepeat: [
  818.         emphasis removeFirst.
  819.         emphasis addLast: (ByteArray new: numberOfColumns withAll: 0)].! !
  820.  
  821. !IntelligentEmulator methodsFor: 'private'!
  822.  
  823. resetDefaults
  824.     "Reset the default parameters"
  825.  
  826.     autoLineFeed _ false.
  827.     autoMargin _ true.
  828.     displayMode _ 0.        "Normal display"! !
  829.  
  830. IntelligentEmulator subclass: #VS100Emulator
  831.     instanceVariableNames: 'state parameters currentParam '
  832.     classVariableNames: ''
  833.     poolDictionaries: ''
  834.     category: 'Interface-TerminalEmulator'!
  835. VS100Emulator comment:
  836. 'I represent a model of a VS100 (DEC) terminal.  I also provide a reasonable
  837. imitation of several other ''ANSI'' terminals, including VT100s.
  838.  
  839. Instance variables:
  840.  
  841. state            This is the state variable for the finite state machine used to
  842.                 interpret the incoming character stream.
  843.  
  844. parameters        An Array of Integers, used to hold the numeric parameters
  845.                 (up to 8) required by ANSI terminals.
  846.  
  847. currentParam    An Integer, representing the current parameter.  Used as an
  848.                 index into the parameters array.
  849. '!
  850.  
  851.  
  852. !VS100Emulator methodsFor: 'initialize-release'!
  853.  
  854. initialize
  855.     "Initialize the state variable."
  856.  
  857.     super initialize.
  858.     self endOfSequence! !
  859.  
  860. !VS100Emulator methodsFor: 'character handling'!
  861.  
  862. addToParameter: char
  863.     "The parameter char is a digit.  Add it to the current parameter."
  864.  
  865.     | param |
  866.     param _ parameters at: currentParam.
  867.     parameters at: currentParam put: (param * 10 + char digitValue)!
  868.  
  869. displayCharacter: char
  870.     "Interpret incoming characters.  A simple state machine is
  871.      implemented using the instance variable state."
  872.  
  873.     (state = 0) ifTrue: [^self processState0: char].
  874.     (state = 1) ifTrue: [^self processState1: char].
  875.     (state = 2) ifTrue: [^self processState2: char].
  876.     (state = 3) ifTrue: [^self processState3: char].
  877.     self error: 'invalid state - this can''t happen'!
  878.  
  879. endOfSequence
  880.     "Clean up after the end of an escape sequence."
  881.  
  882.     state _ 0.
  883.     parameters _ Array new: 8 withAll: 0.
  884.     currentParam _ 1!
  885.  
  886. processState0: char
  887.     "Currently, we are in state 0.  Decide what to do on the
  888.      basis of the parameter char."
  889.  
  890.     (char = Character esc)
  891.         ifTrue: [^state _ 1]
  892.         ifFalse: [^super displayCharacter: char]!
  893.  
  894. processState1: char
  895.     "Currently, we are in state 1.  Decide what to do on the
  896.      basis of the parameter char."
  897.  
  898.     char = $[ ifTrue: [^state _ 2].
  899.     char = $M ifTrue: [
  900.         self cursorUp: 1.
  901.         ^self endOfSequence].
  902.     char = $D ifTrue: [
  903.         self cursorDown: 1.
  904.         ^self endOfSequence].
  905.     ^self doNothing!
  906.  
  907. processState2: char
  908.     "Currently, we are in state 2.  Decide what to do on the
  909.      basis of the parameter char."
  910.  
  911.     char = $; ifTrue: [^currentParam _ (currentParam + 1) min: 8].
  912.     char isDigit ifTrue: [^self addToParameter: char].
  913.     char = $@ ifTrue: [^self insertCharacters].
  914.     char = $A ifTrue: [^self cursorUp].
  915.     char = $B ifTrue: [^self cursorLeft].
  916.     char = $C ifTrue: [^self cursorRight].
  917.     char = $D ifTrue: [^self cursorDown].
  918.     char = $H ifTrue: [^self move].
  919.     char = $J ifTrue: [^self clearDisplay].
  920.     char = $K ifTrue: [^self clearLines].
  921.     char = $L ifTrue: [^self addLines].
  922.     char = $M ifTrue: [^self deleteLines].
  923.     char = $P ifTrue: [^self deleteCharacters].
  924.     char = $m ifTrue: [^self displayMode: (parameters at: 1)].
  925.     char = $r ifTrue: [^self resetDefaults].
  926.     char = $? ifTrue: [^state _ 3].
  927.     ^self doNothing!
  928.  
  929. processState3: char
  930.     "Currently, we are in state 3.  Decide what to do on the
  931.      basis of the parameter char."
  932.  
  933.     char = $; ifTrue: [^currentParam _ (currentParam + 1) min: 8].
  934.     char isDigit ifTrue: [^self addToParameter: char].
  935.     char = $l ifTrue: [
  936.         (parameters at: 1) = 7 ifTrue: [self autoMargin: false].
  937.         ^self doNothing].
  938.     char = $h ifTrue: [
  939.         (parameters at: 1) = 7 ifTrue: [self autoMargin: true].
  940.         ^self doNothing].
  941.     ^self doNothing! !
  942.  
  943. !VS100Emulator methodsFor: 'display manipulation'!
  944.  
  945. addLines
  946.     "Add the appropriate number of blank lines at the position
  947.      indicated by the cursor."
  948.  
  949.     self addLines: ((parameters at: 1) max: 1).
  950.     self endOfSequence!
  951.  
  952. clear
  953.     "Clear the entire display."
  954.  
  955.     super clear.
  956.     self changed: #clear.
  957.     self endOfSequence.!
  958.  
  959. clearDisplay
  960.     "Clear some part of the display."
  961.  
  962.     (parameters at: 1) = 0 ifTrue: [^self clearToEndOfDisplay].
  963.     (parameters at: 1) = 1 ifTrue: [^self clearFromBeginningOfDisplay].
  964.     (parameters at: 1) = 2 ifTrue: [^self clear]!
  965.  
  966. clearEntireLine
  967.     "Override to ensure correct reseting of the state machine."
  968.  
  969.     super clearEntireLine.
  970.     self endOfSequence!
  971.  
  972. clearFromBeginningOfDisplay
  973.     "Override to ensure clean reset of the state machine."
  974.  
  975.     super clearFromBeginningOfDisplay.
  976.     self endOfSequence!
  977.  
  978. clearFromBeginningOfLine
  979.     "Override to ensure correct reseting of the state machine."
  980.  
  981.     super clearFromBeginningOfLine.
  982.     self endOfSequence!
  983.  
  984. clearLines
  985.     "Clear some part of the current line, as indicated by the first parameter."
  986.  
  987.     (parameters at: 1) = 0 ifTrue: [^self clearToEndOfLine].
  988.     (parameters at: 1) = 1 ifTrue: [^self clearFromBeginningOfLine].
  989.     (parameters at: 1) = 2 ifTrue: [^self clearEntireLine]!
  990.  
  991. clearToEndOfDisplay
  992.     "Override to ensure clean reset of the state machine."
  993.  
  994.     super clearToEndOfDisplay.
  995.     self endOfSequence!
  996.  
  997. clearToEndOfLine
  998.     "Override to ensure correct reseting of the state machine."
  999.  
  1000.     super clearToEndOfLine.
  1001.     self endOfSequence!
  1002.  
  1003. cursorDown
  1004.     "Move the cursor down the appropriate number of lines, unless the 
  1005.      cursor would overflow at the bottom."
  1006.  
  1007.     self cursorDown: ((parameters at: 1) max: 1).
  1008.     self endOfSequence!
  1009.  
  1010. cursorLeft
  1011.     "Move the cursor left (in a non-destructive manner) the
  1012.      appropriate number of places, except when the cursor
  1013.      would overflow at the left-hand margin."
  1014.  
  1015.     self cursorLeft: ((parameters at: 1) max: 1).
  1016.     self endOfSequence!
  1017.  
  1018. cursorRight
  1019.     "Move the cursor right (in a non-destructive manner) the 
  1020.      appropriate number of places, except when the cursor 
  1021.      would overflow at the right-hand margin."
  1022.  
  1023.     self cursorRight: ((parameters at: 1) max: 1).
  1024.     self endOfSequence!
  1025.  
  1026. cursorUp
  1027.     "Move the cursor up the appropriate number of lines, unless the cursor 
  1028.      would overflow at the top."
  1029.  
  1030.     self cursorUp: ((parameters at: 1) max: 1).
  1031.     self endOfSequence!
  1032.  
  1033. deleteCharacters
  1034.     "Delete a number of character spaces, as indicated by the first parameter."
  1035.  
  1036.     ((parameters at: 1) max: 1) timesRepeat: [self deleteCharacter].
  1037.     self endOfSequence!
  1038.  
  1039. deleteLines
  1040.     "Delete the appropriate number of lines at the position
  1041.      indicated by the cursor."
  1042.  
  1043.     self deleteLines: ((parameters at: 1) max: 1).
  1044.     self endOfSequence!
  1045.  
  1046. displayMode: anInteger
  1047.     "Override to ensure correct reseting of the state machine."
  1048.  
  1049.     super displayMode: anInteger.
  1050.     self endOfSequence!
  1051.  
  1052. doNothing
  1053.     "Override the superclass in order to reset the state variable."
  1054.  
  1055.     super doNothing.
  1056.     self endOfSequence!
  1057.  
  1058. insertCharacters
  1059.     "Insert a number of character spaces, as indicated by the first parameter."
  1060.  
  1061.     ((parameters at: 1) max: 1) timesRepeat: [self insertCharacter].
  1062.     self endOfSequence!
  1063.  
  1064. move
  1065.     "Move to the locations indicated by the first and second parameters."
  1066.  
  1067.     self moveToX: ((parameters at: 2) max: 1) y: ((parameters at: 1) max: 1).
  1068.     self endOfSequence! !
  1069. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1070.  
  1071. VS100Emulator class
  1072.     instanceVariableNames: ''!
  1073.  
  1074.  
  1075. !VS100Emulator class methodsFor: 'instance creation'!
  1076.  
  1077. openShell
  1078.     "VS100Emulator openShell."
  1079.  
  1080.     IntelligentEmulatorView
  1081.         openOn: (self getTerminal)
  1082.         label: 'Small VS100'!
  1083.  
  1084. openShell: aNumber
  1085.     "VS100Emulator openShell: 1."
  1086.  
  1087.     IntelligentEmulatorView
  1088.         openOn: (self getTerminal: aNumber)
  1089.         label: 'Small VS100'! !
  1090.  
  1091. TermEmulatorView subclass: #IntelligentEmulatorView
  1092.     instanceVariableNames: ''
  1093.     classVariableNames: ''
  1094.     poolDictionaries: ''
  1095.     category: 'Interface-TerminalEmulator'!
  1096. IntelligentEmulatorView comment:
  1097. 'I add the functionality which knows how to display characters with
  1098. various emphasis types.  At present, only ''reverse video'' emphasis is
  1099. supported.
  1100. '!
  1101.  
  1102.  
  1103. !IntelligentEmulatorView methodsFor: 'displaying'!
  1104.  
  1105. reallyDisplayLine: aNumber 
  1106.     "Override the method in the superclass, so that we can deal with 
  1107.      highlighting."
  1108.  
  1109.     | array refPoint pos start highLight |
  1110.     super reallyDisplayLine: aNumber.
  1111.     array _ model emphasisAt: aNumber.
  1112.     refPoint _ insetDisplayBox topLeft + (-3@(aNumber - 1 * CharHeight + 2)).
  1113.     pos _ 0.
  1114.     highLight _ false.
  1115.     [pos _ pos + 1.  pos <= model numberOfColumns] whileTrue: [
  1116.         ((array at: pos) > 0 and: [highLight not]) ifTrue: [
  1117.             highLight _ true.
  1118.             start _ pos].
  1119.         ((array at: pos) = 0 and: [highLight]) ifTrue: [
  1120.             highLight _ false.
  1121.             Display reverse: ((start* 7)@0 + refPoint
  1122.                 extent: (((pos - start)*7)@(CharHeight - 2)))].
  1123.         ((pos = model numberOfColumns) and: [highLight]) ifTrue: [
  1124.             Display reverse: ((start* 7)@0 + refPoint
  1125.                 extent: (((pos - start + 1)*7)@(CharHeight - 2)))]]! !
  1126.  
  1127. MouseMenuController subclass: #TermEmulatorController
  1128.     instanceVariableNames: ''
  1129.     classVariableNames: 'SavedInterruptKey '
  1130.     poolDictionaries: ''
  1131.     category: 'Interface-TerminalEmulator'!
  1132. TermEmulatorController comment:
  1133. 'I represent the controller for a simple terminal emulator.
  1134. '!
  1135.  
  1136.  
  1137. !TermEmulatorController methodsFor: 'initialize-release'!
  1138.  
  1139. initialize
  1140.  
  1141.     super initialize.
  1142.     self initializeYellowButtonMenu!
  1143.  
  1144. release
  1145.     "Overridden to allow some necessary clean-up by TermEmulators."
  1146.  
  1147.     super release.
  1148.     model release! !
  1149.  
  1150. !TermEmulatorController methodsFor: 'basic control sequence'!
  1151.  
  1152. controlInitialize
  1153.     "Save the key that interrupts the system and install a different
  1154.      one so I can have a different meaning for control c."
  1155.  
  1156.     SavedInterruptKey _ InputState interruptKey.
  1157.     InputState interruptKey: 162. "L3 key"
  1158.     ^super controlInitialize!
  1159.  
  1160. controlTerminate
  1161.     "Return the interrupt key to its saved value."
  1162.  
  1163.     InputState interruptKey: SavedInterruptKey.
  1164.     ^super controlTerminate! !
  1165.  
  1166. !TermEmulatorController methodsFor: 'control defaults'!
  1167.  
  1168. controlActivity
  1169.     "Determine whether the user pressed the keyboard.  If so,
  1170.      read the keys."
  1171.  
  1172.     sensor keyboardPressed
  1173.         ifTrue: [self readKeyboard]
  1174.         ifFalse: [super controlActivity]!
  1175.  
  1176. isControlActive
  1177.  
  1178.     ^(view containsPoint: sensor cursorPoint) & sensor blueButtonPressed not! !
  1179.  
  1180. !TermEmulatorController methodsFor: 'menu messages'!
  1181.  
  1182. reset
  1183.     "Reset the terminal port (useful if something has gone wrong)."
  1184.  
  1185.     model reset! !
  1186.  
  1187. !TermEmulatorController methodsFor: 'keyboard input'!
  1188.  
  1189. readKeyboard
  1190.     "Sends keyboard characters to the model (a TermEmulator)."
  1191.  
  1192.     | buffer |
  1193.     buffer _ WriteStream on: (String new: 200).
  1194.     [sensor keyboardPressed] whileTrue: [buffer nextPut: sensor keyboard].
  1195.     (model sendAll: buffer contents) ifFalse: [view flash].! !
  1196.  
  1197. !TermEmulatorController methodsFor: 'private'!
  1198.  
  1199. initializeYellowButtonMenu
  1200.     "Sets up our yellow button commands."
  1201.  
  1202.     self yellowButtonMenu:
  1203.             (PopUpMenu labelList: #((reset)))
  1204.         yellowButtonMessages: #(reset)! !
  1205.  
  1206. VS100Emulator subclass: #LargeVS100Emulator
  1207.     instanceVariableNames: ''
  1208.     classVariableNames: ''
  1209.     poolDictionaries: ''
  1210.     category: 'Interface-TerminalEmulator'!
  1211. LargeVS100Emulator comment:
  1212. 'I represent a ''large'' VS100 terminal, which has 65 lines of 80 columns.
  1213. '!
  1214.  
  1215.  
  1216. !LargeVS100Emulator methodsFor: 'private'!
  1217.  
  1218. initializeLinesAndColumns
  1219.     "The default number of lines and columns are set up here."
  1220.  
  1221.     self setLines: 65.
  1222.     self setColumns: 80.! !
  1223. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1224.  
  1225. LargeVS100Emulator class
  1226.     instanceVariableNames: ''!
  1227.  
  1228.  
  1229. !LargeVS100Emulator class methodsFor: 'instance creation'!
  1230.  
  1231. openShell
  1232.     "LargeVS100Emulator openShell."
  1233.  
  1234.     IntelligentEmulatorView
  1235.         openOn: (self getTerminal)
  1236.         label: 'Large VS100'!
  1237.  
  1238. openShell: aNumber
  1239.     "LargeVS100Emulator openShell: 1."
  1240.  
  1241.     IntelligentEmulatorView
  1242.         openOn: (self getTerminal: aNumber)
  1243.         label: 'Large VS100'! !
  1244.  
  1245. IntelligentEmulator subclass: #NewburyEmulator
  1246.     instanceVariableNames: 'state firstParam '
  1247.     classVariableNames: ''
  1248.     poolDictionaries: ''
  1249.     category: 'Interface-TerminalEmulator'!
  1250. NewburyEmulator comment:
  1251. 'I represent a Newbury 7001/7003 terminal (Ugh!!).
  1252.  
  1253. Instance variables:
  1254.  
  1255. state        A state variable used by the finite state machine which
  1256.             interprets the incoming character stream.
  1257.  
  1258. firstParam    The first numeric parameter supplied when a cursor move
  1259.             operation is specified.
  1260. '!
  1261.  
  1262.  
  1263. !NewburyEmulator methodsFor: 'initialize-release'!
  1264.  
  1265. initialize
  1266.     "Initialize the state variable."
  1267.  
  1268.     super initialize.
  1269.     self endOfSequence! !
  1270.  
  1271. !NewburyEmulator methodsFor: 'character handling'!
  1272.  
  1273. displayCharacter: char
  1274.     "Interpret incoming characters.  A simple state machine is
  1275.      implemented using the instance variable state."
  1276.  
  1277.     (state = 0) ifTrue: [^self processState0: char].
  1278.     (state = 1) ifTrue: [^self processState1: char].
  1279.     (state = 2) ifTrue: [^self processState2: char].
  1280.     self error: 'invalid state - this can''t happen'!
  1281.  
  1282. endOfSequence
  1283.     "Clean up after the end of a cursor positioning sequence."
  1284.  
  1285.     state _ 0!
  1286.  
  1287. processState0: char
  1288.     "Currently, we are in state 0.  Decide what to do on the
  1289.      basis of the parameter char."
  1290.  
  1291.     char isAlphaNumeric ifTrue: [^super displayCharacter: char].
  1292.     (char = 1 asCharacter) ifTrue: [^self addLine].
  1293.     (char = 2 asCharacter) ifTrue: [^self deleteLine].
  1294.     (char = 11 asCharacter) ifTrue: [^self cursorUp: 1].
  1295.     (char = 15 asCharacter) ifTrue: [^self deleteCharacter].
  1296.     (char = 16 asCharacter) ifTrue: [^self insertCharacter].
  1297.     (char = 18 asCharacter) ifTrue: [^self displayMode: 1].
  1298.     (char = 19 asCharacter) ifTrue: [^self displayMode: 0].
  1299.     (char = 20 asCharacter) ifTrue: [^self displayMode: 1].
  1300.     (char = 22 asCharacter) ifTrue: [^state _ 1].
  1301.     (char = 24 asCharacter) ifTrue: [^self cursorRight: 1].
  1302.     (char = 25 asCharacter) ifTrue: [^self clearToEndOfLine].
  1303.     (char = 29 asCharacter) ifTrue: [^self home].
  1304.     (char = 31 asCharacter) ifTrue: [
  1305.         self clear.
  1306.         ^self changed: #clear].
  1307.     ^super displayCharacter: char!
  1308.  
  1309. processState1: char
  1310.     "Currently, we are in state 1.  Decide what to do on the
  1311.      basis of the parameter char."
  1312.  
  1313.     firstParam _ char asciiValue - 31.
  1314.     state _ 2!
  1315.  
  1316. processState2: char
  1317.     "Currently, we are in state 2.  Decide what to do on the
  1318.      basis of the parameter char."
  1319.  
  1320.     self moveToX: firstParam y:  (char asciiValue - 31).
  1321.     self endOfSequence! !
  1322. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1323.  
  1324. NewburyEmulator class
  1325.     instanceVariableNames: ''!
  1326.  
  1327.  
  1328. !NewburyEmulator class methodsFor: 'instance creation'!
  1329.  
  1330. openShell
  1331.     "NewburyEmulator openShell."
  1332.  
  1333.     IntelligentEmulatorView
  1334.         openOn: (self getTerminal)
  1335.         label: 'Newbury'!
  1336.  
  1337. openShell: aNumber
  1338.     "NewburyEmulator openShell: 1."
  1339.  
  1340.     IntelligentEmulatorView
  1341.         openOn: (self getTerminal: aNumber)
  1342.         label: 'Newbury'! !
  1343.